/*
 * @copyright: Huang Ding
 * @Author: ding-cx
 * @Date: 2021-03-09 18:01:24
 * @LastEditors: ding-cx
 * @LastEditTime: 2021-04-07 09:51:42
 * @Description: file content
 */

import { handleRequestUrl, handleWsSendData } from "../util";
import * as WebSocket from "ws";
import { EggWebSocket } from "../../ws";
import * as WorkerInterface from "./workerInterface";
import { Agent } from "egg";

import { stream_to_buffer } from "@diyaner/dy-utils/libs/node/files";
import * as fs from "fs";

import * as EventEmitter from "events";

// 用于处理agent上监听业务事件.
const agentInterface = new EventEmitter();

/**
 *ws server的类进行扩展继承。
 *
 * @export
 * @class Connection
 */
export default class WebSocketServer extends WebSocket.Server {
  private agent: Agent;
  /** work 是event类，作为agent进程上业务处理的逻辑入口，请求的event由它发出。 */
  public work: EventEmitter = new EventEmitter();
  constructor(options, callback, agent: Agent) {
    super(options, callback);
    this.agent = agent;
    this.saveConnection();
    WorkerInterface.onSend(this, this.agent);
    this.on("error", (err) => {
      this.agent.coreLogger.error("[egg-ws] WebSocketServer on error : ", err);
    });
    this.on("close", () => {
      this.agent.coreLogger.info("[egg-ws] WebSocketServer on close.");
    });
  }

  /** 保存进自定义的连接池 */
  private saveConnection() {
    this.on("connection", (ws: EggWebSocket, req) => {
      // 发送文件给前端。
      // stream_to_buffer(fs.createReadStream("D:/uploads/ws.png")).then(
      //   (buffer) => {
      //     ws.send(buffer);
      //   }
      // );

      const params = handleRequestUrl(req.url); //根据url划分room，并做一个wsuid作为ws的标识。
      this.agent.coreLogger.info("[egg-ws request url params: ]", params);
      this.pools[params.wsuid] = ws;
      ws.wsuid = params.wsuid;
      ws.room = params.room;
      if (!this.rooms[params.room]) {
        this.rooms[params.room] = {};
      }
      this.rooms[params.room][params.wsuid] = ws;
      // 处理当连接断开后，清除pool中的失效连接。
      this.delConection(ws);
      // 处理ws收信息
      WorkerInterface.onMessage(this, ws, this.agent);

      // 有链接时，把有效连接池广播给所有进程
      this.agent.messenger.sendToApp("ws-get-pools", this.getPools());

      // console.log();
      // console.log("当前连接池：",this.pools);
    });
  }

  private delConection(ws: EggWebSocket) {
    ws.on("close", () => {
      this.pools[ws.wsuid] = undefined;
      this.rooms[ws.room][ws.wsuid] = undefined;
    });
    ws.on("error", (err) => {
      this.agent.coreLogger.error("[egg-ws] ws on error : ", err);
    });
  }

  /** 所有连接，对象形式。ws内置已有数组 */
  pools: {
    [key: string]: EggWebSocket | undefined;
  } = {};

  getPools(): string[] {
    return Object.keys(this.pools).filter(
      (item) => this.pools[item] != undefined
    );
  }

  /** 以room，key保存的ws实例 */
  rooms: {
    /** room房间 */
    [key: string]: {
      /** ws实例 */
      [key: string]: EggWebSocket | undefined;
    };
  } = {};

  /** 广播所有人 */
  broadcast(msg) {
    var msg = handleWsSendData(msg);
    this.clients.forEach((item) => {
      item.send(msg);
    });
  }
}
